package br.com.fiap.vendas.business.service.impl;

import br.com.fiap.vendas.business.dao.interfaces.ClienteDAO;
import br.com.fiap.vendas.business.dao.interfaces.PedidoDAO;
import br.com.fiap.vendas.business.dao.interfaces.ProdutoDAO;
import br.com.fiap.vendas.business.entity.ClienteEntity;
import br.com.fiap.vendas.business.entity.PedidoEntity;
import br.com.fiap.vendas.business.entity.ProdutoEntity;
import br.com.fiap.vendas.business.service.interfaces.PedidoService;
import br.com.fiap.vendas.business.vo.PedidoVO;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.jms.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by jeferson on 1/26/14.
 */
@Remote(PedidoService.class)
@LocalBean
@Stateless
public class PedidoServiceImpl implements PedidoService {

    @EJB
    PedidoDAO pedidoDAO;

    @EJB
    ClienteDAO clienteDAO;

    @EJB
    ProdutoDAO produtoDAO;

    @Resource(mappedName = "java:/ConnectionFactory")
    private ConnectionFactory connectionFactory;

    @Resource(mappedName = "java:/queue/processarPedido")
    private Destination destination;

    private Connection connection;
    private Session session;
    private MessageProducer messageProducer;


    @PostConstruct
    public void init() {
        try {
            connection = connectionFactory.createConnection();
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            messageProducer = session.createProducer(destination);
        } catch (JMSException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @PreDestroy
    public void destroy() {
        if (connection != null) {
            try {
                connection.close();
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void inserirPedido(PedidoVO pedidoVO) {
        if (pedidoVO == null) {
            throw new IllegalArgumentException("pedidoVO nao pode ser nulo !");
        }

        ClienteEntity clienteEntity = clienteDAO.localizarCliente(pedidoVO.getCliente().getId());
        ProdutoEntity produtoEntity = produtoDAO.localizarProduto(pedidoVO.getProduto().getId());
        PedidoEntity pedidoEntity = PedidoEntity.build(pedidoVO, clienteEntity, produtoEntity);
        pedidoDAO.inserirPedido(pedidoEntity);
        pedidoVO.setId(pedidoEntity.getId());

    }

    @Override
    public List<PedidoVO> buscarPedidos() {


        List<PedidoEntity> pedidos = pedidoDAO.buscarPedidos();
        List<PedidoVO> pedidosVO = new ArrayList<PedidoVO>();

        for (PedidoEntity pedidoEntity : pedidos) {
            pedidosVO.add(pedidoEntity.buildVO());
        }
        return pedidosVO;
    }

    @Override
    public void atualizarStatusPedido(PedidoVO pedidoVO) {

        PedidoEntity pedidoEntity = pedidoDAO.localizarPedido(pedidoVO.getId());
        pedidoEntity.setStatus(pedidoVO.getStatus());
        pedidoDAO.atualizarPedido(pedidoEntity);
    }

    public List<PedidoVO> localizarPedidosReservados() {
        List<PedidoEntity> pedidos = pedidoDAO.buscarPedidosReservados();
        List<PedidoVO> pedidosVO = new ArrayList<PedidoVO>();

        for (PedidoEntity pedidoEntity : pedidos) {
            pedidosVO.add(pedidoEntity.buildVO());
        }
        return pedidosVO;
    }

    public List<PedidoVO> localizarProdutosPorValor(final BigDecimal valor) {
        List<PedidoEntity> pedidos = pedidoDAO.buscarPedidosPorValor(valor);
        List<PedidoVO> pedidosVO = new ArrayList<PedidoVO>();

        for (PedidoEntity pedidoEntity : pedidos) {
            pedidosVO.add(pedidoEntity.buildVO());
        }
        return pedidosVO;
    }

    public PedidoVO localizarPedidoPorId(Integer idPedido) {
        return pedidoDAO.localizarPedido(idPedido).buildVO();
    }

    public Integer inserirPedidoAssincrono(PedidoVO pedidoVO) {
        //Insere pedido como criado
        pedidoVO.setStatus("Criado");
        this.inserirPedido(pedidoVO);

        // envia para a fila de aprovacao (assincrono)
        aprovarPedido(pedidoVO);
        return pedidoVO.getId();
    }

    private void aprovarPedido(PedidoVO pedidoVO) {
        ObjectMessage message;
        try {
            message = session.createObjectMessage(pedidoVO);
            messageProducer.send(message);
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

}
